/**
 * 
 */
package net.toocruel.iqismart.service.core.impl;


import net.toocruel.iqismart.dao.RoleRepository;
import net.toocruel.iqismart.dao.core.CategoryRepository;
import net.toocruel.iqismart.entity.common.Category;
import net.toocruel.iqismart.entity.constants.CategoryVisibility;
import net.toocruel.iqismart.entity.rbac.Role;
import net.toocruel.iqismart.entity.rbac.User;
import net.toocruel.iqismart.service.core.CategoryService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.persistence.EntityManager;
import javax.persistence.criteria.*;
import java.util.ArrayList;
import java.util.List;

/**
 * @author toocruel
 *
 */
@Service
@Transactional
public class CategoyyServiceImpl implements CategoryService {

    @Autowired
    private CategoryRepository categoryRepository;

    @Autowired
    private RoleRepository roleRepository;

    @Autowired
    private EntityManager entityManager;

    @Override
    public List<Category> findByVisibilityAndRoles(CategoryVisibility questions, User currentUser) {
        List<Category> all = categoryRepository.findAll(new Specification<Category>() {
            @Override
            public Predicate toPredicate(Root<Category> root, CriteriaQuery<?> query, CriteriaBuilder cb) {
                List<Predicate> predicates = new ArrayList<>();

                SetJoin<Category,Role> joinRole= root.join(root.getModel().getSet("roles",Role.class),JoinType.LEFT);
                Predicate or = null;
                if(currentUser!=null){
                    or = cb.or(joinRole.in(currentUser.getRoles()), joinRole.isNull());
                }else{
                    or = joinRole.isNull();
                }
                predicates.add(or);


                SetJoin<Category,CategoryVisibility> joinVisibility= root.join(root.getModel().getSet("visibilities",CategoryVisibility.class),JoinType.LEFT);
                predicates.add(cb.or(joinVisibility.in(CategoryVisibility.questions),joinVisibility.isNull()));


                return cb.and(predicates.toArray(new Predicate[predicates.size()]));
            }
        });

        return all;
    }

    @Override
    public Category findBySlug(String categorySlug) {
        return categoryRepository.findBySlug(categorySlug);
    }

    @Override
    public Category findById(Long categoryId) {
        return categoryRepository.findOne(categoryId);
    }
}
